package com.itsu.job.components;

import org.springframework.data.redis.core.RedisTemplate;

import java.util.concurrent.TimeUnit;

/**
 * redis加锁工具
 */
public class RedisLockUtil {


    /**
     * 获取一个存活5秒的锁
     *
     * @param redisTemplate redis对象
     * @param key           键
     * @return
     */
    public static boolean trylock(RedisTemplate<String, String> redisTemplate, String key) {
        return lock(redisTemplate, key, Const.LOCK_EXPIRE, Const.LOCK_WAIT);
    }

    /**
     * 获取锁
     *
     * @param redisTemplate redis对象
     * @param key           键
     * @param expireTime    过期时间 毫秒，默认5秒
     * @return
     */
    public static boolean trylock(RedisTemplate<String, String> redisTemplate, String key, long expireTime) {
        return lock(redisTemplate, key, expireTime <= 0 ? Const.LOCK_EXPIRE : expireTime, Const.LOCK_WAIT);
    }

    /**
     * 获取锁
     *
     * @param redisTemplate redis对象
     * @param key           键
     * @param expireTime    过期时间 毫秒，默认5秒
     * @param waitTime      等待时间 毫秒，默认3秒
     * @return
     */
    public static boolean trylock(RedisTemplate<String, String> redisTemplate, String key, long expireTime, long waitTime) {
        return lock(redisTemplate, key, expireTime <= 0 ? Const.LOCK_EXPIRE : expireTime, waitTime <= 0 ? Const.LOCK_WAIT : waitTime);
    }

    /**
     * 加锁
     *
     * @param redisTemplate
     * @param key           键
     * @param expireTime    过期时间 毫秒
     * @param waitTime      等待时间 毫秒
     * @return
     */
    private static boolean lock(RedisTemplate<String, String> redisTemplate, String key, long expireTime, long waitTime) {
        Long start = System.currentTimeMillis();
        while (waitTime < 0 || (System.currentTimeMillis() - start) <= waitTime) {
            Boolean flag = redisTemplate.opsForValue()
                    .setIfAbsent(Const.LOCK_PREFIX + key, String.valueOf(Thread.currentThread().getId()), expireTime,
                            TimeUnit.MILLISECONDS);
            if (flag != null && flag) {
                return true;
            }
        }
        return false;
    }

    /**
     * 解锁
     *
     * @param redisTemplate
     * @param key
     * @return
     */
    public static boolean unlock(RedisTemplate<String, String> redisTemplate, String key) {
        if (key != null) {
            return redisTemplate.delete(Const.LOCK_PREFIX + key);
        }
        return false;
    }

}
